#pragma once

namespace SD_Tools
{
	class ColorTable;
	class ControlOwner;
	class Control;
	class ControlButton;
	class TabView;
	class TextControl;
	class ColorPicker;
	class EditControl;
	class UpDown;
	class TextureControl;
	class Checkbox;
	class Radio;
	class DropDownList;
	class List;
	class Slider;
	class Progress;
	class MultiCheckbox;
	class HotkeyPicker;
	class Window;
	class SilverGui;

	enum SM_KEY
	{
		SMKEY_None = 0,
		SMKEY_LButton = 1,
		SMKEY_RButton = 2,
		SMKEY_Cancel = 3,
		SMKEY_MButton = 4,
		SMKEY_XButton1 = 5,
		SMKEY_XButton2 = 6,
		SMKEY_Back = 8,
		SMKEY_Tab = 9,
		SMKEY_LineFeed = 10,
		SMKEY_Clear = 12,
		SMKEY_Enter = 13,
		SMKEY_Return = 13,
		SMKEY_ShiftKey = 16,
		SMKEY_ControlKey = 17,
		SMKEY_Menu = 18,
		SMKEY_Pause = 19,
		SMKEY_CapsLock = 20,
		SMKEY_Capital = 20,
		SMKEY_KanaMode = 21,
		SMKEY_HanguelMode = 21,
		SMKEY_HangulMode = 21,
		SMKEY_JunjaMode = 23,
		SMKEY_FinalMode = 24,
		SMKEY_KanjiMode = 25,
		SMKEY_HanjaMode = 25,
		SMKEY_Escape = 27,
		SMKEY_IMEConvert = 28,
		SMKEY_IMENonconvert = 29,
		SMKEY_IMEAceept = 30,
		SMKEY_IMEAccept = 30,
		SMKEY_IMEModeChange = 31,
		SMKEY_Space = 32,
		SMKEY_Prior = 33,
		SMKEY_PageUp = 33,
		SMKEY_Next = 34,
		SMKEY_PageDown = 34,
		SMKEY_End = 35,
		SMKEY_Home = 36,
		SMKEY_Left = 37,
		SMKEY_Up = 38,
		SMKEY_Right = 39,
		SMKEY_Down = 40,
		SMKEY_Select = 41,
		SMKEY_Print = 42,
		SMKEY_Execute = 43,
		SMKEY_PrintScreen = 44,
		SMKEY_Snapshot = 44,
		SMKEY_Insert = 45,
		SMKEY_Delete = 46,
		SMKEY_Help = 47,
		SMKEY_0 = 48,
		SMKEY_1 = 49,
		SMKEY_2 = 50,
		SMKEY_3 = 51,
		SMKEY_4 = 52,
		SMKEY_5 = 53,
		SMKEY_6 = 54,
		SMKEY_7 = 55,
		SMKEY_8 = 56,
		SMKEY_9 = 57,
		SMKEY_A = 65,
		SMKEY_B = 66,
		SMKEY_C = 67,
		SMKEY_D = 68,
		SMKEY_E = 69,
		SMKEY_F = 70,
		SMKEY_G = 71,
		SMKEY_H = 72,
		SMKEY_I = 73,
		SMKEY_J = 74,
		SMKEY_K = 75,
		SMKEY_L = 76,
		SMKEY_M = 77,
		SMKEY_N = 78,
		SMKEY_O = 79,
		SMKEY_P = 80,
		SMKEY_Q = 81,
		SMKEY_R = 82,
		SMKEY_S = 83,
		SMKEY_T = 84,
		SMKEY_U = 85,
		SMKEY_V = 86,
		SMKEY_W = 87,
		SMKEY_X = 88,
		SMKEY_Y = 89,
		SMKEY_Z = 90,
		SMKEY_LWin = 91,
		SMKEY_RWin = 92,
		SMKEY_Apps = 93,
		SMKEY_Sleep = 95,
		SMKEY_NumPad0 = 96,
		SMKEY_NumPad1 = 97,
		SMKEY_NumPad2 = 98,
		SMKEY_NumPad3 = 99,
		SMKEY_NumPad4 = 100,
		SMKEY_NumPad5 = 101,
		SMKEY_NumPad6 = 102,
		SMKEY_NumPad7 = 103,
		SMKEY_NumPad8 = 104,
		SMKEY_NumPad9 = 105,
		SMKEY_Multiply = 106,
		SMKEY_Add = 107,
		SMKEY_Separator = 108,
		SMKEY_Subtract = 109,
		SMKEY_Decimal = 110,
		SMKEY_Divide = 111,
		SMKEY_F1 = 112,
		SMKEY_F2 = 113,
		SMKEY_F3 = 114,
		SMKEY_F4 = 115,
		SMKEY_F5 = 116,
		SMKEY_F6 = 117,
		SMKEY_F7 = 118,
		SMKEY_F8 = 119,
		SMKEY_F9 = 120,
		SMKEY_F10 = 121,
		SMKEY_F11 = 122,
		SMKEY_F12 = 123,
		SMKEY_F13 = 124,
		SMKEY_F14 = 125,
		SMKEY_F15 = 126,
		SMKEY_F16 = 127,
		SMKEY_F17 = 128,
		SMKEY_F18 = 129,
		SMKEY_F19 = 130,
		SMKEY_F20 = 131,
		SMKEY_F21 = 132,
		SMKEY_F22 = 133,
		SMKEY_F23 = 134,
		SMKEY_F24 = 135,
		SMKEY_NumLock = 144,
		SMKEY_Scroll = 145,
		SMKEY_LShiftKey = 160,
		SMKEY_RShiftKey = 161,
		SMKEY_LControlKey = 162,
		SMKEY_RControlKey = 163,
		SMKEY_LMenu = 164,
		SMKEY_RMenu = 165,
		SMKEY_BrowserBack = 166,
		SMKEY_BrowserForward = 167,
		SMKEY_BrowserRefresh = 168,
		SMKEY_BrowserStop = 169,
		SMKEY_BrowserSearch = 170,
		SMKEY_BrowserFavorites = 171,
		SMKEY_BrowserHome = 172,
		SMKEY_VolumeMute = 173,
		SMKEY_VolumeDown = 174,
		SMKEY_VolumeUp = 175,
		SMKEY_MediaNextTrack = 176,
		SMKEY_MediaPreviousTrack = 177,
		SMKEY_MediaStop = 178,
		SMKEY_MediaPlayPause = 179,
		SMKEY_LaunchMail = 180,
		SMKEY_SelectMedia = 181,
		SMKEY_LaunchApplication1 = 182,
		SMKEY_LaunchApplication2 = 183,
		SMKEY_Oem1 = 186,
		SMKEY_OemSemicolon = 186,
		SMKEY_Oemplus = 187,
		SMKEY_Oemcomma = 188,
		SMKEY_OemMinus = 189,
		SMKEY_OemPeriod = 190,
		SMKEY_OemQuestion = 191,
		SMKEY_Oem2 = 191,
		SMKEY_Oemtilde = 192,
		SMKEY_Oem3 = 192,
		SMKEY_Oem4 = 219,
		SMKEY_OemOpenBrackets = 219,
		SMKEY_OemPipe = 220,
		SMKEY_Oem5 = 220,
		SMKEY_Oem6 = 221,
		SMKEY_OemCloseBrackets = 221,
		SMKEY_Oem7 = 222,
		SMKEY_OemQuotes = 222,
		SMKEY_Oem8 = 223,
		SMKEY_Oem102 = 226,
		SMKEY_OemBackslash = 226,
		SMKEY_ProcessKey = 229,
		SMKEY_Packet = 231,
		SMKEY_Attn = 246,
		SMKEY_Crsel = 247,
		SMKEY_Exsel = 248,
		SMKEY_EraseEof = 249,
		SMKEY_Play = 250,
		SMKEY_Zoom = 251,
		SMKEY_NoName = 252,
		SMKEY_Pa1 = 253,
		SMKEY_OemClear = 254
	};

	enum SM_WINDOW_PROPERTY
	{
		SMWP_CLOSE_BUTTON = 0x1,
		SMWP_MINIMIZE_BUTTON = 0x2,
		SMWP_NOBORDER = 0x4,
		SMWP_DRAWWINDOW = 0x8,
		SMWP_ALWAYSVISIBLE = 0x10,
		SMWP_NOTOPBAR = 0x20,
		SMWP_MOVEABLE = 0x40,
		SMWP_NOTASKBUTTON = 0x80,

		SMWP_NORMAL = SMWP_CLOSE_BUTTON | SMWP_MINIMIZE_BUTTON | SMWP_MOVEABLE
	};

	enum SM_CONTROL_TYPE
	{
		SMCT_BUTTON,
		SMCT_TAB,
		SMCT_TEXT,
		SMCT_COLORPICKER,
		SMCT_EDIT,
		SMCT_UPDOWN,
		SMCT_TEXTURE,
		SMCT_CHECKBOX,
		SMCT_RADIO,
		SMCT_DROPDOWNLIST,
		SMCT_LISTVIEW,
		SMCT_SLIDER,
		SMCT_PROGRESS,
		SMCT_MULTICHECKBOX,
		SMCT_HOTKEYPICKER
	};

	enum SM_CONTROLOWNER_TYPE
	{
		SMCOT_GUI,
		SMCOT_WINDOW,
		SMCOT_TAB
	};

	enum SM_USER_COMMANDS
	{
		SMUC_SHOW,
		SMUC_HIDE,
		SMUC_TOGGLE
	};

	enum SM_MSG_TYPE
	{
		SMMT_USERCOMMAND,
		SMMT_MOUSEMOVE,
		SMMT_MOUSECLICK,
		SMMT_MOUSERCLICK,
		SMMT_MOUSEDRAG,
		SMMT_MOUSEDROP,
		SMMT_MOUSEENTER,
		SMMT_MOUSELEAVE,
		SMMT_KEY
	};

	enum SM_LISTVIEW_COLUMNTYPE
	{
		SMLVT_WCHAR,
		SMLVT_INT,
		SMLVT_UINT,
		SMLVT_DWORDHEX,
		SMLVT_BOOL,
		SMLVT_BOOLFORMATTED,
		SMLVT_CHECKBOX
	};

	enum SM_EDIT_PROPERTY
	{
		SMEP_SELFEXPENDABLE = 0x1,
		SMEP_READONLY = 0x2,
		SMEP_HOVERFLOW = 0x4,
		SMEP_VOVERFLOW = 0x8,
		SMEP_NUMONLY = 0x10,
		SMEP_ALPHONLY = 0x20,
		SMEP_NOMULTILINE = 0x40,
		SMEP_RIGHTALIGNED = 0x80
	};

	enum SM_PROGRESS_TYPE
	{
		SMPT_NORMAL,
		SMPT_CIRCLE
	};

	struct SM_Msg
	{
		SM_MSG_TYPE Type;
		DWORD ParamA;
		DWORD ParamB;
		SM_Msg(SM_MSG_TYPE Type, DWORD ParamA, DWORD ParamB): Type(Type), ParamA(ParamA), ParamB(ParamB) {};
	};

	struct GuiFontTable
	{
		bool FontsInitialized;
		bool LostDevice;
		bool ResetDevice;
		ID3DXFont* Font;
		ID3DXFont* Font2;
	};

	struct GuiColorTable 
	{
		D3DCOLOR Background;
		// usw...
	};

	struct GuiSizeTable
	{
		float TopBarHeight;
		float BotBarHeight;
		// usw...
	};

	struct WindowColorTable 
	{
		D3DCOLOR Background;
		// usw...
	};

	struct WindowSizeTable
	{
		float TopBarHeight;
		float BotBarHeight;
		// usw...
	};

	struct ControlColorTable
	{
		D3DCOLOR Color1;
		D3DCOLOR Color2;
		D3DCOLOR Color3;
		D3DCOLOR Color4;
		D3DCOLOR InactiveColor1;
		D3DCOLOR InactiveColor2;
		D3DCOLOR InactiveColor3;
		D3DCOLOR InactiveColor4;
	};

	struct ControlSizeTable
	{
		Rectangle2 DrawRect;
		Rectangle2 HitboxRect;
		float Size1;
		float Size2;
		float Size3;
		float Size4;
		float Size5;
		float Size6;
		float Size7;
		float Size8;
	};

	class Control
	{
	private:
	public:
	protected:
		unsigned int Id;
		Rectangle2 DrawRectangle;
		Rectangle2 HitboxRectangle;
		ControlOwner* Parent;
		SM_CONTROL_TYPE Type;
		wchar_t* Comment;
		GuiFontTable* FontTable;
		ControlColorTable* ColorTable;
		ControlSizeTable* SizeTable;
		bool Visible;
		bool Active;
		bool Focus;
	private:
	protected:
	public:
		virtual void OnDraw() { return; };
		virtual void UpdateTexture() = 0;
		virtual bool InputMessage(SM_Msg& Msg) = 0;
		virtual void SetPosition(Vector2& Point) = 0;
		virtual void Move(Vector2& Point) = 0;
		virtual void SetSize(Vector2& Size) = 0;
		virtual void SetDrawRect(Rectangle2& Rect) = 0;
		virtual void SetComment(wchar_t* Comment) = 0;
		virtual void OnResetA() = 0;
		virtual void OnResetB() = 0;
		unsigned int GetId();
		Rectangle2& GetDrawRect();
		Rectangle2& GetHitRect();
		ControlOwner* GetParent();
		SM_CONTROL_TYPE GetType();
		wchar_t* GetComment();
		GuiFontTable* GetFontTable();
		ControlColorTable* GetColorTable();
		ControlSizeTable* GetSizeTable();
		bool IsVisible();
		bool IsActive();
		bool GotFocus();
		void SetFontTable(GuiFontTable* FontTable);
		void SetColorTable(ControlColorTable* ColorTable);
		void SetSizeTable(ControlSizeTable* SizeTable);
		void Activate();
		void Activate(bool Active);
		void Deactivate();
		void Show();
		void Show(bool Visible);
		void Hide();
	};

	class ControlOwner
	{
	private:
	protected:
		int NumberOfControls;
		int MaxNumberOfControls;
		int ActiveControl;
		SM_CONTROLOWNER_TYPE Type;
		Control** Controls;
		Control* CurrentControl;
		IDirect3DTexture9* Texture;
		Rectangle2 DrawRect;
	public:
	private:
	protected:
	public:
		virtual void UpdateTexture(IDirect3DDevice9* Device) = 0;
		virtual void CreateTexture(IDirect3DDevice9* Device) = 0;
		virtual void OnResetA(IDirect3DDevice9* Device) = 0;
		virtual void OnResetB(IDirect3DDevice9* Device) = 0;
		virtual void Draw(IDirect3DDevice9* Device);

		Control* GetControlDrawnAt(Vector2& Point);
		Control* GetControlAt(Vector2& Point);
		Control* GetCurrentControl();
		int GetNumberOfControls();
		int GetMaxNumberOfControls();
		int GetActiveControl();
		SM_CONTROLOWNER_TYPE GetType();
		IDirect3DTexture9* GetTexture();
		Rectangle2& GetDrawRect();
		void SetDrawRect(Rectangle2& Rect);
		Control** GetControls();

		virtual ControlButton* AddButton(Vector2& Position, Vector2& Size, wchar_t* Caption, wchar_t* Comment) = 0;
		virtual TabView* AddTabView(Vector2& Position, Vector2& Size, int NumberOfTabs, wchar_t* Comment) = 0;
		virtual TextControl* AddText(Vector2& Position, DrawTextType Type, wchar_t* Text, wchar_t* Comment) = 0;
		virtual ColorPicker* AddColorPicker(Vector2& Position, Vector2& Size, D3DCOLOR* HandleValue, wchar_t* Comment) = 0;
		virtual EditControl* AddEdit(Vector2& Position, Vector2& Size, wchar_t* HandleText, int MaxChars, DWORD Options, wchar_t* Comment) = 0;
		virtual UpDown* AddUpDown(Vector2& Position, int* HandleValue, wchar_t* Comment) = 0;
		virtual TextureControl* AddTexture(Vector2& Position, Vector2& Size, IDirect3DTexture9* Texture, wchar_t* Comment) = 0;
		virtual Checkbox* AddCheckbox(Vector2& Position, bool* HandleValue, wchar_t* Comment) = 0;
		virtual Radio* AddRadio(Vector2& Position, int GroupId, int* HandleValue, wchar_t* Comment) = 0;
		virtual DropDownList* AddDropDownList(Vector2& Position, int NumberOfItems, wchar_t** ItemCaptions, int* HandleValue, wchar_t* Comment) = 0;
		virtual List* AddListView(Vector2& Position, Vector2& Size, int NumberOfColumns, wchar_t** ColumnCaptions, SM_LISTVIEW_COLUMNTYPE* ColumnTypes, wchar_t* Comment) = 0;
		virtual Slider* AddSlider(Vector2& Position, float* HandleValue, wchar_t* Comment) = 0;
		virtual Progress* AddProgress(Vector2& Position, float* HandleValue, wchar_t* Comment) = 0;
		virtual MultiCheckbox* AddMultiCheckbox(Vector2& Position, int* HandleValue, wchar_t* Comment) = 0;
		virtual HotkeyPicker* AddHotkeyPicker(Vector2& Position, DWORD* HandleValue, wchar_t* Comment) = 0;

	};

	typedef void(* ButtonCallback_t)();

	class ControlButton : public Control
	{
	private:
		wchar_t* Caption;
		ButtonCallback_t Callback;
	public:
	private:
	public:
		ControlButton(Vector2& Position, ControlOwner* Parent, unsigned int Id, GuiFontTable* FontTable, ControlColorTable* ColorTable, ControlSizeTable* SizeTable, wchar_t* Comment, wchar_t* Caption, ButtonCallback_t Callback = NULL);
		~ControlButton();
		wchar_t* GetCaption();
		void SetCaption(wchar_t* Caption);
		void SetCallback(ButtonCallback_t Callback);
	};

	class TabView : public Control, public ControlOwner
	{
	private:
		int NumberOfTabs;
		int MaxNumberOfTabs;
		int CurrentActiveTab;
		wchar_t** TabCaptions;
		wchar_t** TabComments;
		// Tables...
		int* ControlAssignedTabNumbers;
		int* HandleValue; // CurrentTab
	public:
	private:
	public:
		//TabView(Rectangle2& Position, ControlOwner* Parent, unsigned int Id, GuiFontTable* FontTable, ControlColorTable* ColorTable, ControlSizeTable* SizeTable, wchar_t* Comment, wchar_t* Caption, ButtonCallback_t Callback = NULL);
		//~TabView();
		// TODO: Constructor && Destructor
		int GetNumberOfTabs();
		int GetMaxNumberOfTabs();
		int GetCurrentActiveTabIndex();
		wchar_t* GetCurrentActiveTabCaption();
		void SetHandleValue(int* HandleValue);
		void ForceCurrentTab(int Index);
		wchar_t* GetTabCaption(int Index);
		void SetTabcaption(int Index, wchar_t* Caption);
		void SetTabComment(int Index, wchar_t* Comment);
		int GetTabIndexOfControl(Control* Control);
		int GetTabIndexOfControlIndex(int Index);
	};

	class TextControl : public Control
	{
	private:
		wchar_t* HandleValue;
	public:
	private:
	public:
		TextControl(Vector2& Position, ControlOwner* Parent, unsigned int Id, GuiFontTable* FontTable, ControlColorTable* ColorTable, ControlSizeTable* SizeTable, wchar_t* Comment, wchar_t* Text);
		~TextControl();
		wchar_t* GetText();
		void SetText(wchar_t* Text);
	};

	class ColorPicker : public Control
	{
	private:
		D3DCOLOR* HandleValue;
		IDirect3DTexture9* ColorTexture;
		Vector2 CurrentPickPosition;
	public:
	private:
	public:
		ColorPicker(Vector2& Position, ControlOwner* Parent, unsigned int Id, GuiFontTable* FontTable, ControlColorTable* ColorTable, ControlSizeTable* SizeTable, wchar_t* Comment, D3DCOLOR* HandleValue);
		~ColorPicker();
		D3DCOLOR GetColor();
		D3DCOLOR* GetHandleValue();
		void SetColor(D3DCOLOR Color);
		void SetHandleValue(D3DCOLOR* HandleValue);
	};

	class EditControl : public Control
	{
	private:
		wchar_t* HandleValue;
		int MaxChars;
		int CursorPos;
		Vector2 CursorPosVec;
		// TODO...
	public:
	private:
	public:
		EditControl(Vector2& Position, ControlOwner* Parent, unsigned int Id, GuiFontTable* FontTable, ControlColorTable* ColorTable, ControlSizeTable* SizeTable, wchar_t* Comment, wchar_t* HandleValue); // TODO
		~EditControl();
		// TODO...
	};

	class UpDown : public Control
	{
	private:
		int* HandleValue;
		int LowBorder;
		int HighBorder;
	public:
	private:
	public:
		UpDown(Vector2& Position, ControlOwner* Parent, unsigned int Id, GuiFontTable* FontTable, ControlColorTable* ColorTable, ControlSizeTable* SizeTable, wchar_t* Comment, int* HandleValue, int HighBorder, int LowBorder = 0);
		~UpDown();
		int* GetHandleValue();
		int GetCurrentCount();
		int GetLowBorder();
		int GetHighBorder();
		void SetLowBorder(int LowBorder);
		void SetHighBorder(int HighBorder);
		void SetHandleValue(int* HandleValue);
		void SetCurrentCount(int Count);
	};

	class TextureControl : public Control
	{
	private:
		IDirect3DTexture9* Texture;
	public:
	private:
	public:
		TextureControl(Vector2& Position, ControlOwner* Parent, unsigned int Id, GuiFontTable* FontTable, ControlColorTable* ColorTable, ControlSizeTable* SizeTable, wchar_t* Comment, IDirect3DTexture9* Texture);
		~TextureControl();
		IDirect3DTexture9* GetTexture();
		void SetTexture(IDirect3DTexture9* Texture);
	};

	class Checkbox : public Control
	{
	private:
		bool* HandleValue;
	public:
	private:
	public:
		Checkbox(Vector2& Position, ControlOwner* Parent, unsigned int Id, GuiFontTable* FontTable, ControlColorTable* ColorTable, ControlSizeTable* SizeTable, wchar_t* Comment, bool* HandleValue);
		~Checkbox();
		bool IsChecked();
		bool* GetHandleValue();
		void SetHandleValue(bool* HandleValue);
		void SetChecked(bool Checked);
	};

	class Radio : public Control
	{
	private:
		int GroupId;
		int InternalId;
		int* HandleValue;
	public:
	private:
	public:
		Radio(Vector2& Position, ControlOwner* Parent, unsigned int Id, GuiFontTable* FontTable, ControlColorTable* ColorTable, ControlSizeTable* SizeTable, wchar_t* Comment, int* HandleValue, int GroupId, int InternalId);
		~Radio();
		int GetGroupId();
		int GetInternalId();
		int* GetHandleValue();
		void SetHandleValue(int* HandleValue);
		void SetInternalId(int Id);
	};

	class DropDownList : public Control
	{
	private:
		int NumberOfItems;
		int MaxNumberOfItems;
		wchar_t** ItemTextList;
		int* HandleValue;
		// TODO?
	public:
	private:
	public:
		DropDownList(Vector2& Position, ControlOwner* Parent, unsigned int Id, GuiFontTable* FontTable, ControlColorTable* ColorTable, ControlSizeTable* SizeTable, wchar_t* Comment, int* HandleValue, int NumberOfItems);
		~DropDownList();
		int GetNumberOfItems();
		int GetMaxNumberOfItems();
		int AddItem(wchar_t* ItemCaption);
		int* GetHandleValue();
		int GetCurrentSelection();
		int SetCurrentSelection(int Id);
		wchar_t* GetCaptionByIndex(int Id);
	};

	class List : public Control
	{
	private:
		int NumberOfItems;
		int MaxNumberOfItems;
		int NumberOfColumns;
		wchar_t** ColumnDescriptions;
		SM_LISTVIEW_COLUMNTYPE* ColumnTypes;
		// TODO...
	public:
	private:
	public:
		List(Vector2& Position, ControlOwner* Parent, unsigned int Id, GuiFontTable* FontTable, ControlColorTable* ColorTable, ControlSizeTable* SizeTable, wchar_t* Comment, int* HandleValue);
		~List();
		// TODO... Linked List, etc.
	};

	class Slider : public Control
	{
	private:
		float* HandleValue;
		float LeftBorder;
		float RightBorder;
		float Resolution;
		bool Vertical;
	public:
	private:
	public:
		Slider(Vector2& Position, ControlOwner* Parent, unsigned int Id, GuiFontTable* FontTable, ControlColorTable* ColorTable, ControlSizeTable* SizeTable, wchar_t* Comment, float* HandleValue, bool Vertical = false, float LeftBorder = 0.0f, float RightBorder = 100.0f, float StepSize = 1.0f);
		~Slider();
		float GetCurrentValue();
		float* GetHandleValue();
		float GetLeftBorder();
		float GetRightBorder();
		float GetResolution();
		bool IsVertical();
		void SetCurrentValue(float Value);
		void SetHandleValue(float* HandleValue);
		void SetLeftBorder(float LeftBorder);
		void SetRightBorder(float RightBorder);
		void SetResolution(float Resolution);
		void SetVertical(bool Vertical);
	};

	class Progress : public Control
	{
	private:
		float* HandleValue;
		float LeftBorder;
		float RightBorder;
		float Resolution;
		bool Smooth;
		SM_PROGRESS_TYPE ProgressType;
	public:
	private:
	public:
		Progress(Vector2& Position, ControlOwner* Parent, unsigned int Id, GuiFontTable* FontTable, ControlColorTable* ColorTable, ControlSizeTable* SizeTable, wchar_t* Comment, float* HandleValue, SM_PROGRESS_TYPE = SMPT_NORMAL, bool Vertical = false, float LeftBorder = 0.0f, float RightBorder = 100.0f, float StepSize = 1.0f);
		~Progress();
		float GetCurrentValue();
		float* GetHandleValue();
		float GetLeftBorder();
		float GetRightBorder();
		float GetResolution();
		bool IsSmooth();
		void SetCurrentValue(float Value);
		void SetHandleValue(float* HandleValue);
		void SetLeftBorder(float LeftBorder);
		void SetRightBorder(float RightBorder);
		void SetResolution(float Resolution);
		void SetSmooth(bool Smooth);
		void Increase();
		void Decrease();
	};

	class MultiCheckbox : public Control
	{
	private:
		int* HandleValue;
		int MaxCount;
	public:
	private:
	public:
		MultiCheckbox(Vector2& Position, ControlOwner* Parent, unsigned int Id, GuiFontTable* FontTable, ControlColorTable* ColorTable, ControlSizeTable* SizeTable, wchar_t* Comment, int* HandleValue, int MaxCount);
		~MultiCheckbox();
		int GetCurrentValue();
		int* GetHandleValue();
		int GetMaxCount();
		void SetCurrentValue(int Value);
		void SetHandleValue(int* HandleValue);
		void SetMaxCount(int MaxCount);
	};

	class HotkeyPicker : public Control
	{
	private:
		DWORD* HandleValue;
	public:
	private:
	public:
		HotkeyPicker(Vector2& Position, ControlOwner* Parent, unsigned int Id, GuiFontTable* FontTable, ControlColorTable* ColorTable, ControlSizeTable* SizeTable, wchar_t* Comment, DWORD* HandleValue);
		~HotkeyPicker();
		DWORD GetHotkeys();
		DWORD* GetHandleValue();
		void SetHotkeys(DWORD Hotkeys);
		void SetHandleValue(DWORD* HandleValue);
	};

	class Window : public ControlOwner
	{
	private:
		SilverGui* Parent;
		unsigned int Id;
		Rectangle2 Position;
		wchar_t* Caption;
		wchar_t* Comment;
		DWORD Properties;
		WindowColorTable* ColorTable;
		WindowSizeTable* SizeTable;
		GuiFontTable* FontTable;
		bool Focus;
	public:
	private:
	public:
		void InputMessage(SM_Msg& Msg);
		SilverGui* GetParent();
		unsigned int GetId();
		Rectangle2& GetPosition();
		wchar_t* GetCaption();
		wchar_t* GetComment();
		DWORD GetProperties();
		WindowColorTable* GetColorTable();
		WindowSizeTable* GetSizeTable();
		GuiFontTable* GetFontTable();
		void OnResetA();
		void OnResetB();
		bool GotFocus();
		void SetPosition(Vector2& Point);
		void Move(Vector2& Point);
		void Resize(Vector2& Size);
		void SetCaption(wchar_t* Caption);
		void SetComment(wchar_t* Comment);
		void SetColorTable(WindowColorTable* ColorTable);
		void SetSizeTable(WindowSizeTable* SizeTable);
		void SetFontTable(GuiFontTable* FontTable);
	};

	typedef void(* SilverGuiCallback_t)(SM_Msg& Message);

	class SilverGui : public ControlOwner
	{
	private:
		IDirect3DDevice9* Device;
		D3DVIEWPORT9 DeviceViewport;

		GuiColorTable ColorTable;
		GuiSizeTable SizeTable;
		GuiFontTable FontTable;

		WindowColorTable DefaultWindowColorTable;
		WindowSizeTable DefaultWindowSizeTable;
		GuiFontTable DefaultWindowFontTable;

		ControlColorTable DefaultControlColorTable;
		ControlSizeTable DefaultControlSizeTable;
		GuiFontTable DefaultControlFontTable;

		Window** Windows;
		int NumberOfWindows;
		int MaxNumberOfWindows;

		SilverGuiCallback_t UserCallback;

		Control* ControlBelowMouse;
		Window* WindowBelowMouse;

		wchar_t* Caption;

		bool Visible;
	public:
	private:
		void init();
	public:
		SilverGui(IDirect3DDevice9* Device, int NumberOfWindows, int NumberOfControls, SilverGuiCallback_t Callback, wchar_t* Name);
		~SilverGui();
		void BeforeReset();
		void AfterReset();
		void Submit();
		void InputMessage(SM_Msg& Msg);
		void DisableAll();
		void Show();
		void Show(bool Vis);
		void Hide();
		void Draw();
		void ResetAll();
		void SetCallback(SilverGuiCallback_t NewCallback);
		void SetDevice(IDirect3DDevice9* Device);
		IDirect3DDevice9* GetDevice();
		void SetColorTable(GuiColorTable& ColorTable);
		void SetSizeTable(GuiSizeTable& SizeTable);
		void SetFontTable(GuiFontTable& FontTable);
		void SetDefaultWindowColorTable(WindowColorTable& ColorTable);
		void SetDefaultWindowSizeTable(WindowSizeTable& SizeTable);
		void SetDefaultWindowFontTable(GuiFontTable& FontTable);
		void SetDefaultControlColorTable(ControlColorTable& ColorTable);
		void SetDefaultControlSizeTable(ControlSizeTable& SizeTable);
		void SetDefaultControlFontTable(GuiFontTable& FontTable);
		int GetNumberOfWindows();
		int GetMaxNumberOfWindows();
		Window* GetWindowAt(Vector2& Position);
	};

	SilverGui::SilverGui( IDirect3DDevice9* Device, int NumberOfWindows, int NumberOfControls, SilverGuiCallback_t Callback, wchar_t* Name )
	{
		init();
		this->Device = Device;
		this->MaxNumberOfWindows = NumberOfWindows;
		this->MaxNumberOfControls = NumberOfControls;
		this->UserCallback = Callback;
		this->Caption = new wchar_t[wcslen(Name)+1];
		wcscpy(this->Caption, Name);
	}

	SilverGui::~SilverGui()
	{
		delete[] this->Caption;
		for (int i = 0; i < NumberOfWindows; i++)
		{
			delete this->Windows[i];
		}
		for (int i = 0; i < NumberOfControls; i++)
		{
			delete this->Controls[i];
		}
		// TODO ?
	}

	void SilverGui::BeforeReset()
	{
		for (int i = 0; i < NumberOfControls; i++)
		{
			this->Controls[i]->OnResetA();
		}
		for (int i = 0; i < NumberOfWindows; i++)
		{
			this->Windows[i]->OnResetA();
		}
		this->OnResetA(this->Device);
	}

	void SilverGui::AfterReset()
	{
		for (int i = 0; i < NumberOfControls; i++)
		{
			this->Controls[i]->OnResetB();
		}
		for (int i = 0; i < NumberOfWindows; i++)
		{
			this->Windows[i]->OnResetB();
		}
		this->OnResetB(this->Device);
	}

	void SilverGui::Submit()
	{
		for (int i = 0; i < NumberOfControls; i++)
		{
			this->Controls[i]->UpdateTexture();
		}
		for (int i = 0; i < NumberOfWindows; i++)
		{
			this->Windows[i]->UpdateTexture(this->Device);
		}
		this->UpdateTexture(this->Device);
	}

	void SilverGui::InputMessage( SM_Msg& Msg )
	{
		switch (Msg.Type)
		{
		case SMMT_USERCOMMAND:
			{
				switch (Msg.ParamA)
				{
				case SMUC_SHOW:
					this->Visible = true;
					break;
				case SMUC_HIDE:
					this->Visible = false;
					break;
				case SMUC_TOGGLE:
					this->Visible = !this->Visible;
					break;
				}
			}
			break;
		case SMMT_MOUSEMOVE:
			{
				// TODO:
				// -replace for loop with GetControlAt...
				// -replace for loop with GetWindowAt...
				Vector2 CurrentMousePos(GET_X_LPARAM(Msg.ParamA), GET_Y_LPARAM(Msg.ParamA));
				Control* TempControl;
				Control* LastControlBelowMouse = ControlBelowMouse;
				ControlBelowMouse = NULL;
				for (int i = 0; i < NumberOfControls; i++)
				{
					TempControl = Controls[i];
					if (TempControl->GetHitRect().IsPointIn(CurrentMousePos))
					{
						if (LastControlBelowMouse != TempControl)
						{
							TempControl->InputMessage(SM_Msg(SMMT_MOUSEENTER, Msg.ParamA, 0/*TODO*/));
						}
						ControlBelowMouse = TempControl;
						break;
					}
				}
				if (LastControlBelowMouse != ControlBelowMouse && LastControlBelowMouse != NULL)
				{
					LastControlBelowMouse->InputMessage(SM_Msg(SMMT_MOUSELEAVE, Msg.ParamA, 0/*TODO*/));
				}
				if (ControlBelowMouse)
				{
					// TODO: Msg.ParamB to rel coords
					ControlBelowMouse->InputMessage(Msg);
				}
				//////////////////////////////////////////////////////////////////////////
				Window* TempWindow;
				Window* LastWindowBelowMouse = WindowBelowMouse;
				WindowBelowMouse = NULL;

				for (int i = 0; i < NumberOfWindows; i++)
				{
					TempWindow = Windows[i];
					if (TempWindow->GetPosition().IsPointIn(CurrentMousePos))
					{
						if (LastWindowBelowMouse != TempWindow)
						{
							TempWindow->InputMessage(SM_Msg(SMMT_MOUSEENTER, Msg.ParamA, 0/*TODO*/));
						}
						WindowBelowMouse = TempWindow;
						break;
					}
				}
				if (LastWindowBelowMouse != WindowBelowMouse && LastWindowBelowMouse != NULL)
				{
					LastWindowBelowMouse->InputMessage(SM_Msg(SMMT_MOUSELEAVE, Msg.ParamA, 0/*TODO*/));
				}
				if (ControlBelowMouse)
				{
					// TODO: Msg.ParamB to rel coords
					WindowBelowMouse->InputMessage(Msg);
				}
			}
			break;
		case SMMT_MOUSECLICK: // TODO? Stick together with MOUSERCLICK?
			{
				Vector2 CurrentMousePos(GET_X_LPARAM(Msg.ParamA), GET_Y_LPARAM(Msg.ParamA));
				Control* ControlBelowMouse = this->GetControlAt(CurrentMousePos);
				if (ControlBelowMouse)
				{
					// TODO relative...
					ControlBelowMouse->InputMessage(Msg);
				}
			}
			break;
		case SMMT_MOUSERCLICK:
			{
				Vector2 CurrentMousePos(GET_X_LPARAM(Msg.ParamA), GET_Y_LPARAM(Msg.ParamA));
				Control* ControlBelowMouse = this->GetControlAt(CurrentMousePos);
				if (ControlBelowMouse)
				{
					// TODO relative...
					ControlBelowMouse->InputMessage(Msg);
				}
			}
			break;
		case SMMT_MOUSEDRAG:
			{
				// TODO
			}
			break;
		case SMMT_MOUSEDROP:
			{
				// TODO
			}
			break;
		case SMMT_MOUSEENTER:
			{
				// Useless?
			}
			break;
		case SMMT_MOUSELEAVE:
			{
				// Useless?
			}
			break;
		case SMMT_KEY:
			{
				// TODO:
				// -AltTab?
				// -Other similar hard hotkeys
			}
			break;
		}
	}

	void SilverGui::DisableAll()
	{
		// TODO ka, was die funk sollte
	}

	void SilverGui::Show()
	{
		this->Visible = true;
	}

	void SilverGui::Show( bool Vis )
	{
		this->Visible = Vis;
	}

	void SilverGui::Hide()
	{
		this->Visible = false;
	}

	void SilverGui::Draw()
	{
		// TODO
		this->Device->SetTexture(0, this->Texture);
		// TODO Draw
		for (int i = 0; i < NumberOfWindows; i++)
		{
			this->Windows[i]->Draw(this->Device);
		}
	}

	void SilverGui::ResetAll()
	{
		// TODO
	}

	void SilverGui::SetCallback( SilverGuiCallback_t NewCallback )
	{
		this->UserCallback = NewCallback;
	}

	void SilverGui::SetDevice( IDirect3DDevice9* Device )
	{
		this->Device = Device;
	}

	IDirect3DDevice9* SilverGui::GetDevice()
	{
		return this->Device;
	}

	void SilverGui::SetColorTable( GuiColorTable& ColorTable )
	{
		this->ColorTable = ColorTable;
	}

	void SilverGui::SetSizeTable( GuiSizeTable& SizeTable )
	{
		this->SizeTable = SizeTable;
	}

	void SilverGui::SetFontTable( GuiFontTable& FontTable )
	{
		this->FontTable = FontTable;
	}

	void SilverGui::SetDefaultWindowColorTable( WindowColorTable& ColorTable )
	{
		this->DefaultWindowColorTable = ColorTable;
	}

	void SilverGui::SetDefaultWindowSizeTable( WindowSizeTable& SizeTable )
	{
		this->DefaultWindowSizeTable = SizeTable;
	}

	void SilverGui::SetDefaultWindowFontTable( GuiFontTable& FontTable )
	{
		this->DefaultWindowFontTable = FontTable;
	}

	void SilverGui::SetDefaultControlColorTable( ControlColorTable& ColorTable )
	{
		this->DefaultControlColorTable = ColorTable;
	}

	void SilverGui::SetDefaultControlSizeTable( ControlSizeTable& SizeTable )
	{
		this->DefaultControlSizeTable = SizeTable;
	}

	void SilverGui::SetDefaultControlFontTable( GuiFontTable& FontTable )
	{
		this->DefaultControlFontTable = FontTable;
	}

	int SilverGui::GetNumberOfWindows()
	{
		return this->NumberOfWindows;
	}

	int SilverGui::GetMaxNumberOfWindows()
	{
		return this->MaxNumberOfWindows;
	}

	Window* SilverGui::GetWindowAt( Vector2& Position )
	{
		// TODO Mittag
	}

};

